package com.flame.auth.client.interceptor;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.flame.auth.core.annotation.HasAuth;
import com.flame.auth.core.annotation.HasRole;
import com.flame.auth.core.context.AuthContextHolder;
import com.flame.auth.core.entity.TrustedPrincipal;
import com.flame.auth.core.exception.AuthExceptionMessage;
import com.flame.auth.core.exception.AuthRuntimeException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * @author wuxintong
 * @since 2023/1/1
 */
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 1、校验 Role、Auth 权限
        HasAuth hasAuthAnnotation = ((HandlerMethod) handler).getMethod().getAnnotation(HasAuth.class);
        HasRole hasRoleAnnotation = ((HandlerMethod) handler).getMethod().getAnnotation(HasRole.class);
        if (hasAuthAnnotation == null && hasRoleAnnotation == null) {
            return true;
        }
        TrustedPrincipal trustedPrincipal = AuthContextHolder.getContext();
        boolean hasRole = false;
        if (hasRoleAnnotation != null) {
            Set<String> roleList = trustedPrincipal.getRoleList();
            for (String role : hasRoleAnnotation.value()) {
                if (roleList.contains(role)) {
                    hasRole = true;
                    break;
                }
            }
        }
        boolean hasAuth = false;
        if (hasAuthAnnotation != null) {
            Set<String> authList = trustedPrincipal.getAuthList();
            for (String auth : hasAuthAnnotation.value()) {
                if (authList.contains(auth)) {
                    hasAuth = true;
                    break;
                }
            }
        }
        if (hasRole || hasAuth) {
            return true;
        }
        throw new AuthRuntimeException(AuthExceptionMessage.ACCOUNT_NO_AUTH);
    }
}
